<?php
/**
* DiXon Generation 1 - JavaScript Client Pages
* 
* PHP Bindings for PHP 5.2.x and above
* 
* Copyright (c) 2008, Artem Ploujnikov
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided  that the following conditions are met:
* 
*  * Redistributions of source code must retain the above copyright notice, this 
*    list of conditions and the following disclaimer.
*  * Redistributions in binary form must reproduce the above copyright notice, this 
* 	 list of conditions and the following disclaimer in the documentation and/or 
*    other materials provided with the distribution.
* *  Neither the name of Artem Ploujnikov nor the names of the project's contributors 
* 	 may be used to endorse or promote products derived from this software without 
*    specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
*/


/**
* Represents a DiXon-JSClientPages configuration file. In the
* PHP version, it is implemented using .ini files
* 
* @author Artem Ploujnikov 
*/
class DiXon_Configuration {
	/**
	* The default configuration file
	*/
	const DefaultFileName = 'JSClientPages.ini';
	
	/**
	* The default section name
	*/
	const DefaultSection = 'JSClientPages';
	
	
	/**
	* The name of the section used for error
	* messages
	*/
	const ErrorSection = 'JSClientPages.Errors';

	/**
	* The prefix that is prepended to the error code to
	* identify the error within the JSClientPages.Errors
	* section
	*/
	const ErrorPrefix = 'Error.';
	
	/**
	* The configuration key for the directory
	* where source files reside
	*/
	const SourcePath = 'SourcePath';
	
	
	/**
	* The configuration key for the directory where
	* compiled files reside
	*/                                                  
	const CompiledPath = 'CompiledPath';
	
	/**
	* The configuration key for the full path to the
	* DiXon compiler stylesheer
	*/
	const CompilerStylesheetPath = 'CompilerStylesheetPath';
	
	
	/**
	* The configuration key for the Content-Type used
	* for DiXon-compiled/scripts
	* 
	* Examples:
	* 
	* text/ecmascript
	* text/javascript
	* application/x-javascript
	*/
	const ScriptContentType = 'ScriptContentType';
	
	
	
	/**
	* The name of the configuration
	* file
	* 
	* @var string
	*/
	private $fileName;
	
	
	/**
	* The contents of the configuration file
	* 
	* @var array
	*/
	private $configuration;
	
	/**
	* Creates a new configuration instance
	* 
	* @param string $fileName the name of the configuration 
	* file
	*/
	protected function __construct($fileName) {
		$this->fileName = $fileName;
		$this->configuration = parse_ini_file($fileName, true);
	}
	
	
	/**
	* Returns the name of the .ini file from which this instance
	* was created
	* 
	* @return string
	*/
	public function getFileName() {
		return $this->fileName;
	}
	
	
	/**
	* Returns the value of configuration setting with the specified name
	* in the specified section. If no section is specified,
	* the default section will be used
	* 
	* @param string $name 		the name of the setting
	* @param string $section    the configuration section from which the
	* 	setting will be retrieved
	*/
	public function getValue($name, $section = self::DefaultSection) {
		return 
			$this->hasValue($name, $section) 
			?
			$this->configuration[$section][$name]
			:
			null;				
	}
	
	/**
	* Determines if the specified value exists in this configuration
	* instance
	* 
	* @param string $name the name of the setting to check
	* @param string $section the .ini section where the setting will
	* 	be checked (optional). If no section is provided, the default
	* 	section ('JSClientPages') will be used.
	* 
	* @return bool
	*/
	public function hasValue($name, $section = self::DefaultSection) {
		return 
			isset($this->configuration[$section]) 
			&&
			isset($this->configuration[$section][$name]);
	}
	
	/**
	* Retrieves a configuration value using getValue() and then
	* converts it to a path using toPath(), replaces '/' and '\'
	* characters with the value of DIRECTORY_SEPARATOR
	* 
	* @param string $name 		the name of the configuration parameter
	* @param string $section    the name of the section (optional)
	* 
	* @return string
	*/
	public function getPath($name, $section = self::DefaultSection) {
		return self::toPath(
			$this->getValue($name, $section)
		);
	}
	
	/**
	* Converts cross-platform paths to path definitions for the
	* current platform
	* 
	* @param string $value
	* 
	* @return string
	*/
	public static function toPath($value) {
		return str_replace(
			array('/','\\'),
			array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR),
			$value
		);
	}
	
	/**
	* Contains configuration instances that have
	* already been loaded.
	*/
	private static $instances;
	
	/**
	* Returns an instance of DiXon_Configuration for the 
	* specified file name. 
	*/
	public static function getInstance($fileName = null) {
		if ($fileName === null) {
			$fileName = DIXON_PHP_ROOT . DIRECTORY_SEPARATOR . self::DefaultFileName;
		}
		
		if (!isset(self::$instances[$fileName])) {
			self::$instances[$fileName] = new DiXon_Configuration($fileName);
		} 
		
		return self::$instances[$fileName];
	}
}